


float f_light_contactShadow(in vec2 invResolution, in mat4 viewMaterix, in S_LightArea area, in vec4 inVert, float w) {
	
	float maxDis = area.m_contactShadowLength;

	const int sampleCount = 32;
	const float stepSample = area.m_contactShadowLength / sampleCount;
	vec2 r = area.m_diffusivity * invResolution * 0.1;
	
	//vec3 rayPoint = inVert.xyz - area.m_dir;

	//return 1;
	for(int x = -1; x <= 1; ++x){
		for(int y = -1; y <= 1; ++y){
			
			for (int i = 0; i < sampleCount; ++i) {
				float d = stepSample * (i+1);
				vec3 rayPoint = inVert.xyz - area.m_dir * d;
				//vec3 rayPoint = inVert.xyz;
				float rz = ((viewMaterix * vec4(rayPoint.xyz, 0))).z;

				rayPoint = (viewMaterix * vec4(rayPoint.xyz, 1)).xyz;
				rayPoint.xy *= w;
				rayPoint.xy *= 0.5;
				rayPoint.xy += 0.5;
				//return rayPoint.y;

				vec3 sz = texture(GBuffer_Image[DEF_GBuffer_Vert], rayPoint.xy + vec2(x,y) * r).xyz;
				//vec3 sz = texture(texGBuffer_Vert, rayPoint.xy + vec2(x,y) * r).xyz;
				sz = (viewMaterix * vec4(sz, 0)).xyz;
				
				float z = sz.z - rz;

				
				/*float a = step(area.m_thickness - 0.05, abs(z));
				float b = step(0, z);

				z = clamp(0, area.m_thickness, abs(z));
				z = (z / area.m_thickness) * area.m_contactShadowLength;
				z = min(maxDis, z);
				
				maxDis = min(maxDis, max(d * b, z * a));
				continue;*/

				if(abs(z) >= area.m_thickness - 0.05) {
					z = abs(z);
					maxDis = min(maxDis, (z / area.m_thickness) * area.m_contactShadowLength);
					break;
				}else{
					if (z < 0 ) {
						maxDis = min(maxDis, d);
						break;
					}
				}
			}
		}
	}

	maxDis /= area.m_contactShadowLength;
	//maxDis = clamp(0, 1, maxDis - 0.1);
	//return maxDis;
	return maxDis;
}




float f_light_contactShadowLen(in vec2 invResolution, in mat4 viewMaterix, in S_LightArea area, in vec4 inVert, float w) {
	
	float maxDis = area.m_contactShadowLength;

	const int sampleCount = 32;
	const float stepSample = area.m_contactShadowLength / sampleCount;
	//vec2 r = area.m_diffusivity * invResolution * 0.1;
	
	for (int i = 0; i < sampleCount; ++i) {
		float d = stepSample * (i+1);
		vec3 rayPoint = inVert.xyz - area.m_dir * d;
		float rz = ((viewMaterix * vec4(rayPoint.xyz, 1))).z;

		rayPoint = (viewMaterix * vec4(rayPoint.xyz, 1)).xyz;
		rayPoint.xy *= w;
		rayPoint.xy *= 0.5;
		rayPoint.xy += 0.5;
		//return rayPoint.y;

		vec3 sz = texture(GBuffer_Image[DEF_GBuffer_Vert], rayPoint.xy).xyz;
		//vec3 sz = texture(texGBuffer_Vert, rayPoint.xy + vec2(x,y) * r).xyz;
		sz = (viewMaterix * vec4(sz, 1)).xyz;
		
		float z = sz.z - rz;

		if(abs(z) >= area.m_thickness - 0.05) {
			z = abs(z);
			maxDis = min(maxDis, (z / area.m_thickness) * area.m_contactShadowLength);
			break;
		}else{
			if (z < 0 ) {
				maxDis = min(maxDis, d);
				break;
			}
		}
	}

	maxDis /= area.m_contactShadowLength;
	return maxDis;
}



float f_light_blurShadow(in vec4 inVert, in vec3 inNormal, in vec2 invResolution, in S_LightArea area, in S_LightIndex light, float maxDis) {
	
	mat4 projMatrix0 = m_LightArea_PVMatrix[light.m_matrixIndex];
	vec4 shadowVert = projMatrix0 * vec4(inVert.xyz, 1);

	//shadowVert.xy += 1;
	//shadowVert.xy *= 0.5;
	
	shadowVert.xy *= 0.5;
	shadowVert.xy += 0.5;

	if (any(lessThan(shadowVert.xy, vec2(0.0))) || any(greaterThan(shadowVert.xy, vec2(1.0)))) {
		return 0;
	}
	

	//float s = 0;
	float a = 0;
	float r = area.m_diffusivity * invResolution.x * 10;

	int lightAreaIt = m_constPush.m_shadowSampleNum;
	for(int x = -lightAreaIt; x <= lightAreaIt; ++x){
		for(int y = -lightAreaIt; y <= lightAreaIt; ++y){
			float r1 = pow(r.x * maxDis * 0.1, 1);
			vec2 d = vec2(x, y) * r1;
			//vec2 d = vec2(0);

			//float z1 = texture(GBuffer_Image[DEF_GBuffer_Vert], shadowVert.xy + d).r;
			float z1 = texture(texShadow[light.m_shadowTexIndex], shadowVert.xy + d).r;
			//float z1 = texture(texShadow, shadowVert.xy + d).r;
			z1 = step(0.001, shadowVert.z - z1);
			//z1 = step(0.0001, z1 - shadowVert.z);
			a += 0.2 * z1 / (1+maxDis*0.25);
			//a += 0.2 * z1;
		}
	}
	//return a;

	lightAreaIt = lightAreaIt * 2 + 1;
	a /= (lightAreaIt*lightAreaIt);
	//return shadowVert.z * 10.1;
	//return texture(texShadow, shadowVert.xy).r * 10.1;
	//return texture(texShadow, (projMatrix0 * vec4(inVert.xyz, 0)).xy).r * 10.1;
	//return texture(texShadow, (projMatrix0 * vec4(inVert.xyz, 1)).xy * 0.5 + 0.5).r * 10.1;
	//return texture(texShadow, (inCameraView * vec4(inVert.xyz, 1)).xy * 0.5 + 0.5).r * 10.1;
	
	a = clamp(a * 5.0, 0, 1);
	a *= max(dot(inNormal, -area.m_dir), 0);
	//a *= 2;
	return a;
}


float f_ssao(in vec4 inVert, in vec3 inNormal, in mat4 inCameraView, in vec2 invResolution, in vec2 screenCoords, float w) {
	float AO = 0;

	float courrentPointZ = (inCameraView * vec4(inVert.xyz, 0)).z;
	const vec2 spaceSampleOffset = vec2(1.0f/(m_constPush.m_AO_X_Sample>>2), float(1.0 / m_constPush.m_AO_Y_Sample));

	float ao_tInv = 1 / m_constPush.m_thicknessAO;
	//float w = gl_FragCoord.z * gl_FragCoord.w * 2 + 1;
	vec3 SampleVec;

	float d = 1 / (m_constPush.m_AO_X_Sample * m_constPush.m_AO_Y_Sample);
	

	for(int x = 0; x < m_constPush.m_AO_X_Sample; ++x){
		for(int y = 0; y < m_constPush.m_AO_Y_Sample; ++y){
			float c = 0;
			
			//AO算法1
			SampleVec = f_SphereSampling( (spaceSampleOffset * vec2(x, y) + vec2(1,-0.5)) );
			//SampleVec = f_SphereSampling( (spaceSampleOffset * vec2(x, y) + vec2(0,-0.5)) );
			//SampleVec = f_SphereSampling( spaceSampleOffset * vec2(x, y) );
			//SampleVec.xz = normalize(random(vec2(x, y) + inVert.xy));

			//SampleVec *= w;
			//vec3 tangent = normalize(SampleVec - inNormal * dot(SampleVec, inNormal));
			//vec3 bitangent = cross(inNormal, tangent);
			//mat3 TBN = mat3(tangent, bitangent, inNormal);
			//SampleVec *= TBN;
			//SampleVec *= vec3(1.0f + float(y) * 0.1);

			//SampleVec.xz = random(spaceSampleOffset * vec2(x, y));
			//vec3 SampleVec = (vec3(spaceSampleOffset * x, 0, spaceSampleOffset * y) - 0.5);
			vec2 sv1 = SampleVec.xz * m_constPush.m_radiusAO * invResolution;
			vec4 indirectVert = texture(GBuffer_Image[DEF_GBuffer_Vert], screenCoords + sv1);
			vec3 indirectNormal = texture(GBuffer_Image[DEF_GBuffer_Normal], screenCoords + sv1).xyz;
			float IndirectPointZ = (inCameraView * vec4(indirectVert.xyz, 0)).z;
			
			c = courrentPointZ - IndirectPointZ;

			float depth = (m_constPush.m_AO_X_Sample * x + y) * d;
			if (c < 0 || abs(c) > m_constPush.m_thicknessAO + m_constPush.m_thicknessAO * depth) {
				AO += 1.0f;
			}
			continue;

			//c = IndirectPointZ - courrentPointZ;
			if (c < m_constPush.m_thicknessAO && c > 0) {
				vec3 zVec = inVert.xyz - indirectVert.xyz;
				float z = length(zVec);
				
				z = (z / m_constPush.m_radiusAO);
				c = (c / m_constPush.m_thicknessAO);
				//c = 0;
				//c = c / m_constPush.m_thicknessAO;
				//float d = 1 - abs(min(0, dot(indirectNormal, inNormal)));
				//d = 1 - clamp(0, 1, d);
				AO += 1 - (c * z);
				//AO += 1 - smoothstep(0, 1, c * z);
				//AO += (1 - max(dot(SampleVec, SampleVec),1));// * (1 - abs(dot(indirectNormal, inNormal)));
				//AO += 1;
				break;
			}
		}
	}
	//return courrentPointZ * inVert.w * 0.5 + 0.5;
	//AO = abs(AO);
	AO /= float(m_constPush.m_AO_X_Sample * m_constPush.m_AO_Y_Sample);
	
	//AO -= 0.35;
	AO *= 3;
	

	AO = 1-clamp(AO, 0, 1);
	AO *= m_constPush.m_intensityAO;
	//AO *= 2;
	AO = 1-clamp(AO, 0, 1);
	//AO = clamp(AO, 0, 1);
	
	AO = mix(AO, 1, w);
	//AO = pow(AO, 1);
	return AO;
}
